; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=aggressive-instcombine -mtriple x86_64-none-eabi -mattr=avx2 -S | FileCheck %s

define i64 @f32_i32(float %in) {
; CHECK-LABEL: @f32_i32(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[IN:%.*]] to i64
; CHECK-NEXT:    [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 2147483647)
; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -2147483648)
; CHECK-NEXT:    ret i64 [[MAX]]
;
  %conv = fptosi float %in to i64
  %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
  %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
  ret i64 %max
}

define i64 @f32_i31(float %in) {
; CHECK-LABEL: @f32_i31(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[IN:%.*]] to i64
; CHECK-NEXT:    [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 1073741823)
; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -1073741824)
; CHECK-NEXT:    ret i64 [[MAX]]
;
  %conv = fptosi float %in to i64
  %min = call i64 @llvm.smin.i64(i64 %conv, i64 1073741823)
  %max = call i64 @llvm.smax.i64(i64 %min, i64 -1073741824)
  ret i64 %max
}

define i32 @f32_i16(float %in) {
; CHECK-LABEL: @f32_i16(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[IN:%.*]] to i32
; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 32767)
; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -32768)
; CHECK-NEXT:    ret i32 [[MAX]]
;
  %conv = fptosi float %in to i32
  %min = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
  %max = call i32 @llvm.smax.i32(i32 %min, i32 -32768)
  ret i32 %max
}

define i32 @f32_i8(float %in) {
; CHECK-LABEL: @f32_i8(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi float [[IN:%.*]] to i32
; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 127)
; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -128)
; CHECK-NEXT:    ret i32 [[MAX]]
;
  %conv = fptosi float %in to i32
  %min = call i32 @llvm.smin.i32(i32 %conv, i32 127)
  %max = call i32 @llvm.smax.i32(i32 %min, i32 -128)
  ret i32 %max
}

define i64 @f64_i32(double %in) {
; CHECK-LABEL: @f64_i32(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi double [[IN:%.*]] to i64
; CHECK-NEXT:    [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 2147483647)
; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -2147483648)
; CHECK-NEXT:    ret i64 [[MAX]]
;
  %conv = fptosi double %in to i64
  %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
  %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
  ret i64 %max
}

define i64 @f64_i31(double %in) {
; CHECK-LABEL: @f64_i31(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi double [[IN:%.*]] to i64
; CHECK-NEXT:    [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 1073741823)
; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -1073741824)
; CHECK-NEXT:    ret i64 [[MAX]]
;
  %conv = fptosi double %in to i64
  %min = call i64 @llvm.smin.i64(i64 %conv, i64 1073741823)
  %max = call i64 @llvm.smax.i64(i64 %min, i64 -1073741824)
  ret i64 %max
}

define i32 @f64_i16(double %in) {
; CHECK-LABEL: @f64_i16(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi double [[IN:%.*]] to i32
; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 32767)
; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -32768)
; CHECK-NEXT:    ret i32 [[MAX]]
;
  %conv = fptosi double %in to i32
  %min = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
  %max = call i32 @llvm.smax.i32(i32 %min, i32 -32768)
  ret i32 %max
}

define i64 @f16_i32(half %in) {
; CHECK-LABEL: @f16_i32(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi half [[IN:%.*]] to i64
; CHECK-NEXT:    [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 2147483647)
; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -2147483648)
; CHECK-NEXT:    ret i64 [[MAX]]
;
  %conv = fptosi half %in to i64
  %min = call i64 @llvm.smin.i64(i64 %conv, i64 2147483647)
  %max = call i64 @llvm.smax.i64(i64 %min, i64 -2147483648)
  ret i64 %max
}

define i64 @f16_i31(half %in) {
; CHECK-LABEL: @f16_i31(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi half [[IN:%.*]] to i64
; CHECK-NEXT:    [[MIN:%.*]] = call i64 @llvm.smin.i64(i64 [[CONV]], i64 1073741823)
; CHECK-NEXT:    [[MAX:%.*]] = call i64 @llvm.smax.i64(i64 [[MIN]], i64 -1073741824)
; CHECK-NEXT:    ret i64 [[MAX]]
;
  %conv = fptosi half %in to i64
  %min = call i64 @llvm.smin.i64(i64 %conv, i64 1073741823)
  %max = call i64 @llvm.smax.i64(i64 %min, i64 -1073741824)
  ret i64 %max
}

define i32 @f16_i16(half %in) {
; CHECK-LABEL: @f16_i16(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi half [[IN:%.*]] to i32
; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 32767)
; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -32768)
; CHECK-NEXT:    ret i32 [[MAX]]
;
  %conv = fptosi half %in to i32
  %min = call i32 @llvm.smin.i32(i32 %conv, i32 32767)
  %max = call i32 @llvm.smax.i32(i32 %min, i32 -32768)
  ret i32 %max
}

define i32 @f16_i8(half %in) {
; CHECK-LABEL: @f16_i8(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi half [[IN:%.*]] to i32
; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.smin.i32(i32 [[CONV]], i32 127)
; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.smax.i32(i32 [[MIN]], i32 -128)
; CHECK-NEXT:    ret i32 [[MAX]]
;
  %conv = fptosi half %in to i32
  %min = call i32 @llvm.smin.i32(i32 %conv, i32 127)
  %max = call i32 @llvm.smax.i32(i32 %min, i32 -128)
  ret i32 %max
}

define <4 x i64> @v4f32_i32(<4 x float> %in) {
; CHECK-LABEL: @v4f32_i32(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi <4 x float> [[IN:%.*]] to <4 x i64>
; CHECK-NEXT:    [[MIN:%.*]] = call <4 x i64> @llvm.smin.v4i64(<4 x i64> [[CONV]], <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>)
; CHECK-NEXT:    [[MAX:%.*]] = call <4 x i64> @llvm.smax.v4i64(<4 x i64> [[MIN]], <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>)
; CHECK-NEXT:    ret <4 x i64> [[MAX]]
;
  %conv = fptosi <4 x float> %in to <4 x i64>
  %min = call <4 x i64> @llvm.smin.v4i64(<4 x i64> %conv, <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>)
  %max = call <4 x i64> @llvm.smax.v4i64(<4 x i64> %min, <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>)
  ret <4 x i64> %max
}

define <8 x i32> @v8f16_i16(<8 x half> %in) {
; CHECK-LABEL: @v8f16_i16(
; CHECK-NEXT:    [[CONV:%.*]] = fptosi <8 x half> [[IN:%.*]] to <8 x i32>
; CHECK-NEXT:    [[MIN:%.*]] = call <8 x i32> @llvm.smin.v8i32(<8 x i32> [[CONV]], <8 x i32> <i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767>)
; CHECK-NEXT:    [[MAX:%.*]] = call <8 x i32> @llvm.smax.v8i32(<8 x i32> [[MIN]], <8 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768>)
; CHECK-NEXT:    ret <8 x i32> [[MAX]]
;
  %conv = fptosi <8 x half> %in to <8 x i32>
  %min = call <8 x i32> @llvm.smin.v8i32(<8 x i32> %conv, <8 x i32> <i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767, i32 32767>)
  %max = call <8 x i32> @llvm.smax.v8i32(<8 x i32> %min, <8 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768, i32 -32768>)
  ret <8 x i32> %max
}


declare i64 @llvm.smin.i64(i64, i64)
declare i64 @llvm.smax.i64(i64, i64)
declare i32 @llvm.smin.i32(i32, i32)
declare i32 @llvm.smax.i32(i32, i32)
declare <2 x i64> @llvm.smin.v2i64(<2 x i64>, <2 x i64>)
declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>)
declare <4 x i64> @llvm.smin.v4i64(<4 x i64>, <4 x i64>)
declare <4 x i64> @llvm.smax.v4i64(<4 x i64>, <4 x i64>)
declare <8 x i64> @llvm.smin.v8i64(<8 x i64>, <8 x i64>)
declare <8 x i64> @llvm.smax.v8i64(<8 x i64>, <8 x i64>)
declare <4 x i32> @llvm.smin.v4i32(<4 x i32>, <4 x i32>)
declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>)
declare <8 x i32> @llvm.smin.v8i32(<8 x i32>, <8 x i32>)
declare <8 x i32> @llvm.smax.v8i32(<8 x i32>, <8 x i32>)
